#pragma once

#include "Util.h"
#include "RTW_stb_image.h"
#include "Perlin.h"

class CTexture {
public:
	virtual ~CTexture() = default;

	virtual Color value(double u, double v, const Point3& vPoint)const = 0;
};

class CSolidColor : public CTexture {
public:
	CSolidColor(const Color& vAlbedo) :m_Albedo(vAlbedo) {}
	CSolidColor(double vRed, double vGreen, double vBlue) : CSolidColor(Color(vRed, vGreen, vBlue)) {}

	Color value(double u, double v, const Point3& vPoint)const override { return m_Albedo; }

private:
	Color m_Albedo;
};

class CCheckerTexture :public CTexture {
public:
	CCheckerTexture(double vScale, shared_ptr<CTexture>(vEven), shared_ptr<CTexture>(vOdd))
		:m_InvScale(1.0 / vScale), m_Even(vEven), m_Odd(vOdd) {}
	CCheckerTexture(double vScale, Color vColor1, Color vColor2)
		: m_InvScale(1.0 / vScale), m_Even(make_shared<CSolidColor>(vColor1)), m_Odd(make_shared<CSolidColor>(vColor2)) {}

	Color value(double u, double v, const Point3& vPoint)const override;

private:
	double m_InvScale;
	shared_ptr<CTexture> m_Even;
	shared_ptr<CTexture> m_Odd;
};

class CImageTexture : public CTexture {
public:
	CImageTexture(const char* vFilename) :m_Image(vFilename) {}

	Color value(double u, double v, const Point3& vPoint)const override;

private:
	rtw_image m_Image;
};

class CNoiseTexture :public CTexture {
public:
	CNoiseTexture(double vScale) :m_Scale(vScale) {};

	Color value(double u, double v, const Point3& vPoint)const override;

private:
	CPerlin m_Perlin;
	double m_Scale;
};

